package com.piece.core.framework.support.response;

import com.piece.core.framework.exception.ErrorCode;
import com.piece.core.framework.util.collection.ArrayUtil;
import com.piece.core.framework.util.object.BeanUtil;
import com.piece.core.framework.util.string.StringUtil;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.apache.commons.collections4.map.CaseInsensitiveMap;
import org.apache.commons.httpclient.HttpStatus;
import java.io.Serializable;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * Ajax请求业务封装结果
 */
@Data
@NoArgsConstructor
public class AjaxResponse implements Serializable {
    /**
     * 编码
     * 错误码参见 {@link ErrorCode}
     */
    private int code;

    /**
     * 请求编号
     */
    private String requestId;

    /**
     * 错误信息
     */
    private String msg;

    /**
     * 响应数据
     */
    private Object param;

    /**
     * 响应头
     */
    private Map<String, List<String>> headers;

    /**
     * 初始化一个新创建的 AjaxResult 对象
     *
     * @param errorCode 错误码
     */
    public AjaxResponse(String requestId, ErrorCode errorCode) {
        this.requestId = requestId;
        this.code = errorCode.getCode();
        this.msg = errorCode.getMsg();
    }

    /**
     * 初始化一个新创建的 AjaxResult 对象
     *
     * @param errorCode 错误码
     */
    public AjaxResponse(ErrorCode errorCode) {
        this.code = errorCode.getCode();
        this.msg = errorCode.getMsg();
    }

    /**
     * 初始化一个新创建的 AjaxResult 对象
     *
     * @param errorCode 错误码
     */
    public AjaxResponse(String requestId, ErrorCode errorCode, Object param) {
        this.requestId = requestId;
        this.code = errorCode.getCode();
        this.msg = errorCode.getMsg();
        this.param = param;
    }

    /**
     * 初始化一个新创建的 AjaxResult 对象
     *
     * @param errorCode 错误码
     */
    public AjaxResponse(ErrorCode errorCode, Object param) {
        this.code = errorCode.getCode();
        this.msg = errorCode.getMsg();
        this.param = param;
    }

    /**
     * 初始化一个新创建的 AjaxResult 对象
     *
     * @param code 状态类型
     * @param msg  返回消息
     */
    public AjaxResponse(int code, String msg) {
        this.code = code;
        this.msg = msg;
    }

    /**
     * 初始化一个新创建的 AjaxResult 对象
     *
     * @param code  状态类型
     * @param msg   返回消息
     * @param param 数据对象
     */
    public AjaxResponse(int code, String msg, Object param) {
        this.code = code;
        this.msg = msg;
        this.param = param;
    }

    /**
     * 初始化一个新创建的 AjaxResult 对象
     *
     * @param code  状态类型
     * @param msg   返回消息
     * @param param 数据对象
     */
    public AjaxResponse(int code, String msg, Object param, Map<String, List<String>> headers) {
        this.code = code;
        this.msg = msg;
        this.param = param;
        this.headers = headers;
    }

    /**
     * 返回错误消息
     *
     * @param msg 内容
     * @return 错误消息
     */
    public static AjaxResponse error(String msg) {
        return error(HttpStatus.SC_INTERNAL_SERVER_ERROR, msg);
    }

    /**
     * 返回错误消息
     *
     * @param msg 内容
     * @return 错误消息
     */
    public static AjaxResponse error(String msg, Object param) {
        return error(HttpStatus.SC_INTERNAL_SERVER_ERROR, msg, param);
    }

    /**
     * 返回错误消息
     *
     * @param code 错误码
     * @param msg  内容
     * @return 错误消息
     */
    public static AjaxResponse error(int code, String msg) {
        return error(code, msg, null);
    }

    /**
     * 返回错误消息
     *
     * @param code  错误码
     * @param msg   内容
     * @param param 数据对象
     * @return 错误消息
     */
    public static AjaxResponse error(int code, String msg, Object param) {
        return new AjaxResponse(code, msg, param);
    }

    /**
     * 返回成功消息
     *
     * @param msg 内容
     * @return 成功消息
     */
    public static AjaxResponse success(String msg) {
        return success(msg, null);
    }

    /**
     * 返回成功消息
     *
     * @param param 响应信息
     * @return 成功消息
     */
    public static AjaxResponse success(String msg, Object param) {
        return new AjaxResponse(HttpStatus.SC_OK, msg, param);
    }

    /**
     * 返回成功消息
     *
     * @param msg     内容
     * @param param   响应信息
     * @param headers 响应头
     * @return 成功消息
     */
    public static AjaxResponse successWithHeader(String msg, Object param, Map<String, List<String>> headers) {
        return resultWithHeader(HttpStatus.SC_OK, msg, param, headers);
    }

    /**
     * 返回消息
     */
    public static AjaxResponse result(ErrorCode errorCode, Object param) {
        return new AjaxResponse(null, errorCode, param);
    }

    /**
     * 返回消息
     */
    public static AjaxResponse result(String requestId, ErrorCode errorCode, Object param) {
        return new AjaxResponse(requestId, errorCode, param);
    }

    /**
     * 返回消息
     */
    public static AjaxResponse resultWithHeader(int code, String msg, Object param, Map<String, List<String>> headers) {
        AjaxResponse response = new AjaxResponse(code, msg, param);
        response.setHeaders(headers);
        return response;
    }

    public String getHeader(String name) {
        if (StringUtil.isEmpty(name)) {
            return null;
        } else {
            CaseInsensitiveMap<String, List<String>> headersIgnoreCase = new CaseInsensitiveMap<>(headers);
            List<String> headerList = headersIgnoreCase.get(name.trim());
            return ArrayUtil.isEmpty(headerList.toArray()) ? null : headerList.get(0);
        }
    }

    public boolean isSuccess() {
        return HttpStatus.SC_OK == getCode();
    }

    public <T> T convertSingleParam(final Class<T> clazz) {
        try {
            T entity = BeanUtil.newInstance(clazz);
            Object source = getParam();
            BeanUtil.copyProperties(source, entity, true);
            return entity;
        } catch (Exception e) {
            return null;
        }
    }

    public <T> List<T> convertListParam(final Class<T> clazz) {
        try {
            Object source = getParam();
            if (ArrayUtil.isArray(source)) {
                List<T> collect = (List<T>) ((List) source).stream().map(param -> {
                    T entity = BeanUtil.newInstance(clazz);
                    BeanUtil.copyProperties(param, entity, true);
                    return entity;
                }).collect(Collectors.toList());
                return collect;
            } else {
                return Collections.singletonList(convertSingleParam(clazz));
            }
        } catch (Exception e) {
            return Collections.emptyList();
        }
    }
}
